﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PokerClient.Connection.Interfaces;
using System.Threading;

namespace PokerClient.VisualDisp {
	public partial class Table : Form, IChangeWindow
	{
		String tableid,maxBuy,minBuy;
		Label[] labels;
		Label[] chips;
		PictureBox[] pictures;
		Button[] buttons;
		GuiSeat[] seats;
		Client myClient;
		Lobby lobby;
		String cardyp, cardh;
		int tSeat;
		Boolean inSeat = false;
		delegate void updateLabel(Label label,String s);
		delegate void updateButton(Button btn,Boolean value);
		delegate void updateTextbar(String s);
		delegate void updateSeat(Seat seat);
		Random rand = new Random();

		public Table(Client myClient,Lobby lobby,String tableid, String max,String min)  
		{
			InitializeComponent();
			this.myClient = myClient;
			this.tableid = tableid;
			this.maxBuy = max;
			this.minBuy = min;			
			this.lobby = lobby;
			this.myClient.assignTable = this;
			this.myClient.currentWindow = this;
			this.Text += ":" + tableid + " Min:" + min + " Max:" + max;
			init();			

		}
		private void init()
		{
			labels = new Label[] {this.label2,this.label3,this.label4,this.label5,this.label6,this.label7,this.label8,this.label9,this.label10};
			pictures = new PictureBox[]{cardB2,cardB3,cardB4,cardB5,cardB6,cardB7,cardB8,cardB9,cardB10,cardB11,cardB12,cardB13,cardB14,cardB15,cardB16,cardB17,
			cardB18,cardB19};
			chips = new Label[] {this.chips2, this.chips3, this.chips4, this.chips5, this.chips6, this.chips7, this.chips8, this.chips9, this.chips10 };
			seats = new GuiSeat[9];
			for (int i = 0, j = 0 ; i < seats.Length; i++,j++)
			{
				seats[i] = new GuiSeat(labels[i],chips[i], pictures[j++], pictures[j]);
			}
			buttons = new Button[] {this.button2, this.button3, this.button4, this.button5, this.button6, this.button7, this.button8, this.button9, this.button10 };
			
			for (int i = 0; i < labels.Length; i++)
			{
				//setlableName(labels[i], "Vacant");
				seats[i].updateChips("0");
				seats[i].updateStat("Vacant");
			}
			
			setCards();
			resetTable();
			
			System.Threading.Thread.Sleep(50);
			this.myClient.sent(PokerClient.Connection.Protocols.ProtocolsRequests.requestUserList(this.myClient.sTable));//tableid));
		}

		private void setCards()
		{
			int jk = rand.Next(0, 5);
			switch (jk)
			{
				case 1:
					cardyp = "bv.jpg";
					cardh = "bh.jpg";
					break;
				case 2:
					cardyp = "blv.jpg";
					cardh = "blh.jpg";
					break;
				case 3:
					cardyp = "gv.jpg";
					cardh = "gh.jpg";
					break;
				default:
					cardyp = "rv.jpg";
					cardh = "rh.jpg";
					break;

			}
		}

		private void resetTable()
		{			
			for (int i = 0; i < seats.Length; i++)
			{				
				
					seats[i].setCards(("Cards\\" + cardyp),("Cards\\" + cardyp));
									
			}
			this.tableCard1.ImageLocation = "Cards\\" + cardyp;
			this.tableCard2.ImageLocation = "Cards\\" + cardyp;
			this.tableCard3.ImageLocation = "Cards\\" + cardyp;
			this.tableCard4.ImageLocation = "Cards\\" + cardyp;
			this.tableCard5.ImageLocation = "Cards\\" + cardyp;

		}

		public void setlableName(Label label, String name)
		{
			if (label.InvokeRequired)
			{
				updateLabel ul = new updateLabel(setlableName);
				label.Invoke(ul, new object[] { label, name });
			}
			else
			{
				label.Text = name;
			}
		}

		public void endisButtons(Button btn, Boolean val)
		{
			if (btn.InvokeRequired)
			{
				updateButton ub = new updateButton(endisButtons);
				btn.Invoke(ub, new object[] { btn, val });
			}
			else
			{
				btn.Visible = val;
			}

		}

		
		public void allocatePlayers(String playerlist)
		{
			for (int i = 0; i < seats.Length; i++)
			{
				if (seats[i].name.Equals("Vacant")) 
					seats[i].hide();
			}
			String[] genlist = playerlist.Split(' ', ':');
			for (int i = 2; i < genlist.Length - 1; i++)
			{
				try
				{
					if(genlist[i].Equals(""))
						continue;
					int j = Int32.Parse(genlist[i++]);
					seats[j].sChips = genlist[i++];
					seats[j].name = genlist[i];
					endisButtons(buttons[j], false);
					seats[j].show();
				}
				catch (System.Exception ex)
				{
					Console.WriteLine(ex.Message);
				}
			}
			
		}		

		private void disButtons(int except)
		{
			for (int i = 0; i < buttons.Length; i++)
			{
				if (i != except)
				{
					endisButtons(buttons[i],false);
				}
			}
		}

		private void enButtons()
		{
			for (int i = 0; i < seats.Length; i++)
			{
				if (seats[i].name == "Vacant")
				{
					endisButtons(buttons[i], true);
				}
			}
		}

		private void updateGroupText(String s)
		{
			if (this.groupBox1.InvokeRequired)
			{
				updateTextbar ut = new updateTextbar(updateGroupText);
				this.groupBox1.Invoke(ut, new object[] { s });
			}
			else
			{
				this.groupBox1.Text = s;
			}
		}

		public void revealFlop(String card1, String card2, String card3)
		{
			String[] gencard1 = card1.Split(':');
			String[] gencard2 = card2.Split(':');
			String[] gencard3 = card3.Split(':');
			this.tableCard1.ImageLocation = "Cards\\" + gencard1[0] + "\\" + gencard1[1] + ".jpg";
			this.tableCard2.ImageLocation = "Cards\\" + gencard2[0] + "\\" + gencard2[1] + ".jpg";
			this.tableCard3.ImageLocation = "Cards\\" + gencard3[0] + "\\" + gencard3[1] + ".jpg";
		}

		public void revealTurn(String card)
		{
			String[] gencard1 = card.Split(':');
			this.tableCard4.ImageLocation = "Cards\\" + gencard1[0] + "\\" + gencard1[1] + ".jpg";
		}

		public void revealRiver(String card)
		{
			String[] gencard1 = card.Split(':');
			this.tableCard5.ImageLocation = "Cards\\" + gencard1[0] + "\\" + gencard1[1] + ".jpg";
		}

		public void updatePlayerCards(String card1, String card2)
		{
			this.seat1.setCards(card1, card2);
		}

		public void changeScreen(string formname)
		{
			throw new NotImplementedException();
		}

		public void updateStatus(string s)
		{
			if (this.textBox1.InvokeRequired)
			{
				updateTextbar tbar = new updateTextbar(updateStatus);
				this.textBox1.Invoke(tbar, new object[] { s });
			}
			else
			{
				this.textBox1.Text = s;
			}
		}

		private void joinSeat(String seatid)
		{
			String t = PokerClient.Connection.Protocols.ProtocolJoinTableSet.joinSeat(this.tableid, seatid,this.maxBuy);
			this.myClient.sSeat = seatid;
			this.myClient.sent(t);
			this.updateStatus(t);
			
		}

		public void leavSeat()
		{
			try
			{
				int i = Int32.Parse(myClient.sSeat);
				seats[i].name = "Vacant";
				seats[i].sChips = "0";
				inSeat = false;
				enButtons();
			}
			catch (System.Exception ex)
			{
				this.updateStatus(ex.Message);
			}
		}

		public void joinGame()
		{			
			this.seat1.client = myClient;
			this.seat1.sTable = this;
			this.seat1.chip = myClient.chip;
			this.seat1.user = myClient.usern;
			this.seat1.grayin();
			try
			{
				int i = Int32.Parse(this.myClient.sSeat);
				seats[i].name = this.myClient.usern;
				seats[i].sChips = this.myClient.chip;
				tSeat = i;
				this.disButtons(i);
				this.endisButtons(buttons[i], false);
				updateGroupText(myClient.usern);
				int j = Int32.Parse(this.maxBuy);
				this.seat1.adjustChips(i);
				//this.seat1.Refresh();
				//this.myClient.sent(PokerClient.Connection.Protocols.ProtocolsRequests.requestUserList(tableid));
				this.inSeat = true;
				seats[i].show();
			}
			catch (System.Exception ex)
			{
				this.updateStatus(ex.Message);
			}
		}

		private void button2_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("0");
			else
				leavSeat();
		}

		private void button3_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("1");
			else
				leavSeat();
		}

		private void button4_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("2");
			else
				leavSeat();
		}

		private void button5_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("3");
			else
				leavSeat();
		}

		private void button6_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("4");
			else
				leavSeat();
		}

		private void button7_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("5");
			else
				leavSeat();
		}

		private void button8_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("6");
			else
				leavSeat();
		}

		private void button9_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("7");
			else
				leavSeat();
		}

		private void button10_Click(object sender, EventArgs e)
		{
			if (!inSeat)
				joinSeat("8");
			else
				leavSeat();
		}

		internal void assignCHips(string[] commands)
		{
		
			String[] temp = commands[2].Split(',',':');
			for (int i = 0; i < temp.Length ; i++)
			{
				int j = 0 ;
				if ((j = findIndex(temp[i++])) > -1)
				{
					seats[j].sChips = temp[i]; 
				}
			}
		}

		private int findIndex(String name)
		{
			int j = -1;
			for (int i = 0; i < seats.Length; i++)
			{
				if (seats[i].name == name)
				{
					return i;
				}
			}
			return j;
		}

		public void turn(String playername, String potsize)
		{
			if (this.seat1.user.Equals(playername))
			{
				this.seat1.grayin();
				this.seat1.setCall(potsize);			

			}
			else
			{
				this.updateStatus(playername + " ,CurrPot:" + potsize + " Need to call:" + potsize);
			}
			this.updateCurrPlayer(playername);
		}

		public void playerFold(String playername)
		{
			int j = -1;
			if ((j = findIndex(playername)) > -1)
			{
				updateStatus(playername + " Folded!");
				seats[j].hide();
			}
		}
		
		public void checkCall(String playername)
		{
			this.updateStatus(playername +" has called\\checked");
		}

		public void playerRaised(String playername,String val)
		{
			this.updateStatus(playername + " has raised by:" + val);

		}

		public void updateBig(String s)
		{
			if (this.bigTB.InvokeRequired)
			{
				updateTextbar ut = new updateTextbar(updateBig);
				this.bigTB.Invoke(ut, new object[] { s });
			}

			else
			{
				this.bigTB.Text = s;
			}
		}

		public void updateSmall(String s)
		{
			if (this.smallTB.InvokeRequired)
			{
				updateTextbar ut = new updateTextbar(updateSmall);
				this.smallTB.Invoke(ut, new object[] { s });
			}

			else
			{
				this.smallTB.Text = s;
			}
		}

		public void updateCurrPot(String s)
		{
			if (this.potTB.InvokeRequired)
			{
				updateTextbar ut = new updateTextbar(updateCurrPot);
				this.potTB.Invoke(ut, new object[] { s });
			}

			else
			{
				this.potTB.Text = s;
			}

		}

		public void updateCurrPlayer(String s)
		{
			if (this.turnTb.InvokeRequired)
			{
				updateTextbar ut = new updateTextbar(updateCurrPlayer);
				this.turnTb.Invoke(ut, new object[] { s });
			}
			else
			{
				this.turnTb.Text = (s + "'s Turn");
			}
		}

		private void button1_Click(object sender, EventArgs e)
		{
			this.revealRiver("1:2");
			this.revealTurn("2:2");
			this.revealFlop("3:A", "4:6", "2:A");
			this.updatePlayerCards("3:2", "2:5");
		}


		
		internal string showHands(string[] temp)
		{
			String message = "fail";
			for (int i = 0; i < temp.Length; i++)
			{
				try
				{
					String[] t = temp[i].Split('#');
					message = analyzeHand(t[0],t[1]);
				}
				catch (Exception e)
				{
					message = e.Message;
				}
				
			}
			return message;
		}

		public string showHands(string p)
		{
			try
			{
				String[] temp = p.Split('#');				
				String ans = analyzeHand(temp[0],temp[1]);
				return (ans);
			}
			catch (Exception e)
			{
				return e.Message;
			}
		}

		private String analyzeHand(String name, String cards)
		{
			String[] temp = cards.Split(',');
			int j = -1;
			if ((j = findIndex(name)) > -1)
			{
				this.seats[j].setCards(temp[0], temp[1]);
				this.seats[j].show();
				return "Success";
			}
			else			
				return "fail";
		}

		internal void announceWinner(string message)
		{
			if (this.winTB.InvokeRequired) 
			{
				updateTextbar ut = new updateTextbar(announceWinner);
				winTB.Invoke(ut, new object[] { message });
			}
			else
			{
				this.winTB.Text = message;
				Thread.Sleep(1000);
				this.resetTable();
			}
			
		}

		internal void resetCards()
		{
			resetTable();
		}

		
	}

	class GuiSeat
	{
		Label l,chips;
		PictureBox card1, card2;
		String pname = "Vacant";
		delegate void setCard1(String card1);
		delegate void setCard2(String card2);
		delegate void updateLable(String name);
		delegate void hideLable();
		delegate void showLable();
		delegate void hideCard1();
		delegate void showCard1();
		public GuiSeat(Label name,Label chips, PictureBox card1, PictureBox card2)
		{
			this.l = name;
			this.card1 = card1;
			this.card2 = card2;
			this.chips = chips;
		}

		public String name
		{
			get
			{
				return this.l.Text;
			}
			set
			{
				this.pname = value;
				updateStat(pname);
			}
		}

		public String sChips
		{
			get
			{
				return this.chips.Text;
			}
			set
			{
				updateChips(value);
			}
		}
		public void setCards(String card1,String card2)
		{
			updateCard1(card1);
			updateCard2(card2);
		}

		private void updateCard1(String cards1)
		{
			if (this.card1.InvokeRequired)
			{
				setCard1 sc1 = new setCard1(updateCard1);
				this.card1.Invoke(sc1, new object[] { cards1 });
			}
			else
			{
				String[] t = cards1.Split(':');
				if (t.Length > 1)
					this.card1.ImageLocation = "Cards\\" + t[0] + "\\" + t[1] + ".jpg";
				else
					this.card1.ImageLocation = cards1;
			}
		}
		private void updateCard2(String cards2)
		{
			if (this.card2.InvokeRequired)
			{
				setCard2 sc2 = new setCard2(updateCard2);
				this.card2.Invoke(sc2, new object[] { cards2 });
			}
			else
			{
				String[] t = cards2.Split(':');
				if (t.Length > 1)
					this.card2.ImageLocation = "Cards\\" + t[0] + "\\" + t[1] + ".jpg";
				else
					this.card2.ImageLocation = cards2;
			}
		}

		public void updateStat(String s)
		{
			if (this.l.InvokeRequired)
			{
				updateLable ul = new updateLable(updateStat);
				this.l.Invoke(ul, new object[] { s });
			}
			else
			{
				this.l.Text = s;
			}
		}

		public void updateChips(String s)
		{
			if (this.chips.InvokeRequired)
			{
				updateLable ul = new updateLable(updateChips);
				this.chips.Invoke(ul, new object[] { s });
			}
			else
			{
				this.chips.Text = s;
			}
		}

		public void hide()
		{
			this.hideName();
			this.hidesCard1();
			this.hidesCard2();
			this.hideChips();
		}

		private void hideName()
		{
			if (this.l.InvokeRequired)
			{
				hideLable hl = new hideLable(hideName);
				this.l.Invoke(hl);
			}
			else
			{
				this.l.Visible = false;
			}
		}
		private void hideChips()
		{
			if (this.chips.InvokeRequired)
			{
				hideLable hl = new hideLable(showChips);
				this.chips.Invoke(hl);
			}
			else
			{
				this.chips.Visible = false;
			}
		}
		private void showName()
		{
			if (this.l.InvokeRequired)
			{
				hideLable hl = new hideLable(showName);
				this.l.Invoke(hl);
			}
			else
			{
				this.l.Visible = true;
			}
		}
		private void showChips()
		{
			if (this.chips.InvokeRequired)
			{
				hideLable hl = new hideLable(showChips);
				this.chips.Invoke(hl);
			}
			else
			{
				this.chips.Visible = true;
			}
		}

		private void hidesCard1()
		{
			if (this.card1.InvokeRequired)
			{
				hideCard1 hl = new hideCard1(hidesCard1);
				this.card1.Invoke(hl);
			}
			else
			{
				this.card1.Visible = false;
			}
		}
		private void hidesCard2()
		{
			if (this.card2.InvokeRequired)
			{
				hideCard1 hl = new hideCard1(hidesCard2);
				this.card2.Invoke(hl);
			}
			else
			{
				this.card2.Visible = false;
			}
		}
		private void showsCard1()
		{
			if (this.card1.InvokeRequired)
			{
				showCard1 sh = new showCard1(showsCard1);
				this.card1.Invoke(sh);
			}
			else
			{
				this.card1.Visible = true;
			}
		}
		private void showsCard2()
		{
			if (this.card2.InvokeRequired)
			{
				showCard1 sh = new showCard1(showsCard2);
				this.card2.Invoke(sh);
			}
			else
			{
				this.card2.Visible = true;
			}
		}
		public void show()
		{
			this.showName();
			this.showsCard1();
			this.showsCard2();
			this.showChips();
		}
	}
}
